<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PostgreSQL Object View Tool</title>
    <link rel="stylesheet" href="/static/style.css">
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #f5f5f5;
        }
        .header {
            background-color: #078722;
            color: white;
            padding: 15px 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .header h2 {
            margin: 0;
        }
        .header .db-info {
            font-size: 14px;
        }
        .container {
            display: flex;
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            padding: 20px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }
        .left-panel {
            width: 30%;
            padding-right: 20px;
            border-right: 1px solid #ddd;
        }
        .right-panel {
            width: 70%;
            padding-left: 20px;
        }
        .form-group {
            margin-bottom: 15px;
        }
        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
        }
        input, select, button {
            width: 100%;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        button {
            background-color: #3d8fed;
            color: white;
            border: none;
            cursor: pointer;
            margin-top: 10px;
        }
        button:hover {
            background-color: #45a049;
        }
        textarea { 
            width: 100%;
            height: 400px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-family: monospace;
            resize: none;
        }
        
        #codeContainer {
            position: relative;
        }
        pre {
            position: relative;
            background-color: #282c34; 
            border: 1px solid #444;
            border-radius: 4px;
            padding: 15px;
            margin: 0;
            height: 400px;
            overflow: auto;
            font-family: Consolas, Monaco, 'Andale Mono', monospace;
            font-size: 14px;
            line-height: 1.5;
            color: #abb2bf;
            white-space: pre-wrap; 
        }
        code {
            background-color: transparent !important;
            padding: 0 !important;
            color: inherit;
            display: block; 
        }
        
        .hljs-button {
            position: absolute;
            top: 5px;
            right: 5px;
            background-color: #9999AA;
            color: white;
            border: none;
            border-radius: 4px;
            padding: 3px 8px;
            font-size: 12px;
            cursor: pointer;
            z-index: 10;
            display: none;
            opacity: 0.6;
            transition: opacity 0.2s, background-color 0.2s;
        }
        .hljs-button:hover {
            opacity: 1;
            background-color: #888899;
        }

        
        .copy-success-tip {
            position: absolute;
            right: 4px;
            top: 4px;
            font-size: 12px;
            color: #ffffff;
            background-color: #4CAF50;
            padding: 2px 8px;
            z-index: 20;
            margin: 8px;
            border-radius: 4px;
            display: none;
        }
        .error {
            color: red;
            margin-top: 5px;
        }
    </style>
</head>
<body>
    <div class="header">
        <h2>PostgreSQL 对象结构查看器</h2>
        <div class="db-info" id="dbInfo"></div>
    </div>
    <div class="container">
        <div class="left-panel">
            <h3>获取对象结构的方式</h3>
            <div class="form-group">
                <div style="display: flex; justify-content: center; margin-bottom: 10px;">
                    <div style="flex: 1; margin-right: 5px; align-items: center;">
                        <input type="radio" id="selectMode" name="tableMode" value="select" checked>
                        <label for="selectMode" style="display: inline">选择方式获取</label>
                    </div>
                    <div style="flex: 1; margin-right: 5px; align-items: center;">
                        <input type="radio" id="searchMode" name="tableMode" value="search">
                        <label for="searchMode" style="display: inline;">搜索方式获取</label>
                    </div>
                </div>
            </div>

            <div id="selectModePanel">
                <h3 style="margin-top: 20px;">选择模式和对象</h3>
            <div class="form-group">
                <label for="schema">模式</label>
                <select id="schema" disabled>
                    <option value="">选择一个模式</option>
                </select>
            </div>
            <div class="form-group">
                <label for="objectType">对象类型</label>
                <select id="objectType">
                    <option value="table">表</option>
                    <option value="view">视图</option>
                    <option value="matview">物化视图</option>
                    <option value="sequence">序列</option>
                    <option value="type">类型</option>
                    <option value="function">函数</option>
                    <option value="procedure">存储过程</option>
                    <option value="trigger">触发器</option>
                </select>
            </div>
            <div class="form-group">
                <label for="table">对象名称</label>
                <select id="table" disabled>
                    <option value="">选择一个对象名称</option>
                </select>
            </div>
            </div>

            <div id="searchModePanel" style="display: none;">
                <h3 style="margin-top: 20px;">搜索模式和对象</h3>
                <div class="form-group">
                    <label for="searchSchema">模式</label>
                    <select id="searchSchema">
                        <option value="">所有模式</option>
                    </select>
                </div>
                <div class="form-group">
                    <label for="searchTable">对象名称</label>
                    <input type="text" id="searchTable" placeholder="输入对象关键字">
                </div>
                <button id="searchBtn">搜索对象</button>
                <div class="form-group" style="margin-top: 15px;">
                    <label for="searchResults">搜索结果</label>
                    <select id="searchResults" size="5" style="height: 120px;">
                        <option value="">请先搜索对象名称</option>
                    </select>
                </div>
            </div>

            <button id="getDDLBtn" disabled>获取DDL语句</button>
            <button id="getIndexDDLBtn" disabled style="margin-top: 10px;">获取索引DDL</button>
        </div>
        <div class="right-panel">
            <div class="title-container">
                <h3>DDL 语句</h3>
            </div>
            <div class="form-group" id="codeContainer" style="position: relative;">
                <pre id="ddlOutputPre" class="prettyprint"><code id="ddlOutputCode"></code></pre>
                <div class="hljs-button" id="copyBtn" data-title="复制" style="display: none;">复制</div>
            </div>
            <textarea id="ddlOutput" readonly></textarea>
        </div>
    </div>

    <script src="/static/jquery-3.6.0.min.js"></script>
    <script src="/static/sql-formatter.min.js"></script>
    <script>
        // 显示数据库连接信息
        $(document).ready(function() {
            // 显示数据库连接信息
            const dbConfig = JSON.parse('{{ db_config|tojson|safe }}');
            $('#dbInfo').text(`${dbConfig.username}@${dbConfig.host}:${dbConfig.port}/${dbConfig.database}`);

            // 初始化页面时自动加载模式列表
            // 加载模式列表
            $.ajax({
                url: '/schemas',
                method: 'GET',
                success: function(response) {
                    if (response.status === 'success') {
                        $('#schema').empty().append('<option value="">选择模式</option>');
                        response.schemas.forEach(function(schema) {
                            $('#schema').append(`<option value="${schema}">${schema}</option>`);
                        });
                        $('#schema').prop('disabled', false);
                    }
                }
            });

            // 切换表选择模式
            $('input[name="tableMode"]').change(function() {
                const mode = $(this).val();
                if (mode === 'select') {
                    $('#selectModePanel').show();
                    $('#searchModePanel').hide();
                    // 重置搜索结果
                    $('#searchResults').empty().append('<option value="">请先搜索对象名称</option>');
                } else {
                    $('#selectModePanel').hide();
                    $('#searchModePanel').show();
                    // 加载搜索模式下拉框
                    if ($('#searchSchema option').length <= 1) {
                        $.ajax({
                            url: '/schemas',
                            method: 'GET',
                            success: function(response) {
                                if (response.status === 'success') {
                                    $('#searchSchema').empty().append('<option value="">所有模式</option>');
                                    response.schemas.forEach(function(schema) {
                                        $('#searchSchema').append(`<option value="${schema}">${schema}</option>`);
                                    });
                                }
                            }
                        });
                    }
                }
                // 重置获取DDL按钮状态
                $('#getDDLBtn').prop('disabled', true);
            });
            
            // 函数/存储过程搜索
            $('#searchInput').on('input', function() {
                const searchTerm = $(this).val();
                const schema = $('#schemaSelect').val();
                const objectType = $('#objectType').val();
                
                // 如果是函数或存储过程搜索，使用专用接口
                if (objectType === 'function' || objectType === 'procedure') {
                    $.ajax({
                        url: '/search_functions',
                        data: {
                            search_term: searchTerm,
                            schema: schema
                        },
                        success: function(data) {
                            if (data.success) {
                                // 处理搜索结果
                                const suggestions = data.data.map(item => ({
                                    name: item.name,
                                    display: item.display_name,
                                    type: item.type
                                }));
                                showSearchSuggestions(suggestions);
                            }
                        }
                    });
                    return;
                }
            });

            // 搜索对象按钮点击事件
            $('#searchBtn').click(function() {
                const searchTerm = $('#searchTable').val();
                const schema = $('#searchSchema').val();
                
                if (!searchTerm) {
                    alert('请输入对象关键字');
                    return;
                }
                
                console.log("搜索对象 - 关键字:", searchTerm, "模式:", schema);  // 调试日志
                
                // 构建搜索参数
                const searchParams = {
                    search_term: searchTerm,
                    schema: schema || undefined, // 不传则搜索所有模式
                    object_type: $('#objectType').val() || undefined // 不传则搜索所有类型
                };
                
                // 统一搜索接口
                $.ajax({
                    url: '/search_objects',
                    method: 'GET',
                    data: searchParams,
                    success: function(response) {
                        console.log("搜索结果:", response);
                        if (response.status === 'success') {
                            $('#searchResults').empty();
                            if (!response.objects || response.objects.length === 0) {
                                $('#searchResults').append('<option value="">未找到匹配的对象</option>');
                                $('#getDDLBtn').prop('disabled', true);
                                $('#getIndexDDLBtn').prop('disabled', true);
                            } else {
                                // 确保函数只显示一次
                                response.objects.forEach(function(obj) {
                                    let displayText;
                                    
                                    // 对于函数/存储过程，直接显示schema.name(参数列表)格式
                                    if (obj.type === 'function' || obj.type === 'procedure') {
                                        // 只显示"schema.name(参数列表)"格式，不包含"(function)"
                                        displayText = obj.name;
                                        // 添加data-oid属性存储oid
                                        $('#searchResults').append(
                                            `<option value="${obj.schema}|${obj.name}|${obj.type}|${obj.oid}" 
                                            data-type="${obj.type}" data-oid="${obj.oid}">${displayText}</option>`
                                        );
                                    } else {
                                        displayText = `${obj.schema}.${obj.name} (${obj.type})`;
                                        $('#searchResults').append(
                                            `<option value="${obj.schema}|${obj.name}|${obj.type}" 
                                            data-type="${obj.type}">${displayText}</option>`
                                        );
                                    }
                                });
                                // 如果只有一个结果，自动选中
                                if (response.objects.length === 1) {
                                    $('#searchResults').val(response.objects[0].schema + '|' + response.objects[0].name + '|' + response.objects[0].type);
                                    $('#getDDLBtn').prop('disabled', false);
                                    $('#getIndexDDLBtn').prop('disabled', response.objects[0].type !== 'table');
                                }
                            }
                        } else {
                            console.error("搜索错误:", response.message || "未知错误");
                            $('#searchResults').empty().append('<option value="">搜索出错: ' + (response.message || "未知错误") + '</option>');
                            $('#getDDLBtn').prop('disabled', true);
                            $('#getIndexDDLBtn').prop('disabled', true);
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error("搜索请求错误:", status, error);
                        $('#searchResults').empty().append('<option value="">搜索请求错误</option>');
                        $('#getDDLBtn').prop('disabled', true);
                        $('#getIndexDDLBtn').prop('disabled', true);
                    }
                });
            });
            
            // 搜索结果选择事件
            $('#searchResults').change(function() {
                const value = $(this).val();
                if (value && value !== '未找到匹配的表' && value !== '请先搜索对象名称' && value !== '搜索出错') {
                    $('#getDDLBtn').prop('disabled', false);
                } else {
                    $('#getDDLBtn').prop('disabled', true);
                }
            });

            // 复制功能
            $('#copyBtn').click(function() {
                const ddlText = $('#ddlOutputCode').text();
                if (!ddlText) {
                    alert('没有内容可复制');
                    return;
                }
                
                // 创建一个临时textarea元素
                const textarea = document.createElement('textarea');
                textarea.value = ddlText;
                textarea.setAttribute('readonly', '');
                textarea.style.position = 'absolute';
                textarea.style.left = '-9999px';
                document.body.appendChild(textarea);
                
                // 选择文本并复制
                textarea.select();
                let success = false;
                try {
                    success = document.execCommand('copy');
                } catch (err) {
                    console.error('复制失败:', err);
                }
                
                // 删除临时元素
                document.body.removeChild(textarea);
                
                // 提示用户
                if (success) {
                    // 显示复制成功提示
                    const copyBtn = $(this);
                    const originalText = copyBtn.text();
                    copyBtn.text('已复制');
                    copyBtn.css('background-color', '#4CAF50');
                    
                    // 1秒后恢复原样
                    setTimeout(() => {
                        copyBtn.text(originalText);
                        copyBtn.css('background-color', '#9999AA');
                    }, 1000);
                } else {
                    // 使用现代API作为备选
                    try {
                        navigator.clipboard.writeText(ddlText).then(function() {
                            const copyBtn = $('#copyBtn');
                            const originalText = copyBtn.text();
                            copyBtn.text('已复制');
                            copyBtn.css('background-color', '#4CAF50');
                            
                            setTimeout(() => {
                                copyBtn.text(originalText);
                                copyBtn.css('background-color', '#9999AA');
                            }, 2000);
                        }, function() {
                            alert('复制失败，请手动复制');
                        });
                    } catch (err) {
                        alert('复制失败，请手动复制');
                    }
                }
            });

            // 加载模式列表
            $.ajax({
                url: '/schemas',
                method: 'GET',
                success: function(response) {
                    if (response.status === 'success') {
                        $('#schema').empty().append('<option value="">选择模式</option>');
                        response.schemas.forEach(function(schema) {
                            $('#schema').append(`<option value="${schema}">${schema}</option>`);
                        });
                    }
                }
            });

            // 模式选择变化时加载表、视图或物化视图列表
            $('#schema').change(function() {
                const schema = $(this).val();
                const objectType = $('#objectType').val();
                if (!schema) {
                    $('#table').empty().append('<option value="">选择一个对象名称</option>').prop('disabled', true);
                    $('#getDDLBtn').prop('disabled', true);
                    return;
                }

                const endpoint = objectType === 'view' ? '/views' : 
                               objectType === 'matview' ? '/matviews' : 
                               objectType === 'sequence' ? '/sequences' :
                               objectType === 'type' ? '/types' : '/tables';
                
                $.ajax({
                    url: endpoint,
                    method: 'GET',
                    data: { schema: schema },
                    success: function(response) {
                        if (response.status === 'success') {
                            $('#table').empty().append('<option value="">选择一个对象名称</option>');
                            const items = objectType === 'view' ? response.views : 
                                         objectType === 'matview' ? response.matviews : 
                                         objectType === 'sequence' ? response.sequences :
                                         objectType === 'type' ? response.types : response.tables;
                            items.forEach(function(item) {
                                $('#table').append(`<option value="${item}">${item}</option>`);
                            });
                            $('#table').prop('disabled', false);
                        }
                    }
                });
            });

            // 对象类型变化时重新加载列表
            $('#objectType').change(function() {
                const type = $(this).val();
                if ($('#schema').val()) {
                    if (type === 'function') {
                        loadFunctions();
                    } else if (type === 'procedure') {
                        loadProcedures();
                    } else if (type === 'trigger') {
                        loadTriggers();
                    } else {
                        $('#schema').trigger('change');
                    }
                }
            });

            function loadFunctions() {
                const schema = $('#schema').val();
                if (!schema) return;
                
                $.get('/functions', { schema: schema }, function(data) {
                    if (data.status === 'success') {
                        $('#table').empty().append('<option value="">选择函数</option>');
                        data.functions.forEach(item => {
                            $('#table').append(`<option value="${item.name}" data-oid="${item.oid}">${item.display_name}</option>`);
                        });
                    }
                });
            }

            function loadProcedures() {
                const schema = $('#schema').val();
                if (!schema) return;
                
                $.get('/procedures', { schema: schema }, function(data) {
                    if (data.status === 'success') {
                        $('#table').empty().append('<option value="">选择存储过程</option>');
                        data.procedures.forEach(item => {
                            $('#table').append(`<option value="${item.name}" data-oid="${item.oid}">${item.display_name}</option>`);
                        });
                    }
                });
            }

            function loadTriggers() {
                const schema = $('#schema').val();
                if (!schema) return;
                
                $.get('/triggers', { schema: schema }, function(data) {
                    if (data.status === 'success') {
                        $('#table').empty().append('<option value="">选择触发器</option>');
                        data.triggers.forEach(trig => {
                            $('#table').append(`<option value="${trig}">${trig}</option>`);
                        });
                    }
                });
            }

            // 表选择变化时启用获取DDL按钮
            $('#table').change(function() {
                const hasValue = !!$(this).val();
                $('#getDDLBtn').prop('disabled', !hasValue);
                $('#getIndexDDLBtn').prop('disabled', !hasValue);
            });

            $('#searchResults').change(function() {
                const value = $(this).val();
                const hasValue = value && value !== '未找到匹配的表' && value !== '请先搜索对象名称' && value !== '搜索出错';
                $('#getDDLBtn').prop('disabled', !hasValue);
                $('#getIndexDDLBtn').prop('disabled', !hasValue);
                
                // 更新对象类型下拉框以匹配搜索结果
                if (hasValue) {
                    const parts = value.split('|');
                    if (parts.length > 2) {
                        const type = parts[2];
                        $('#objectType').val(type);
                    }
                }
            });

            // 获取DDL语句
            // 获取索引DDL
            $('#getIndexDDLBtn').click(function() {
                let schema, table;
                
                // 根据当前模式获取schema和table
                if ($('#selectMode').is(':checked')) {
                    schema = $('#schema').val();
                    table = $('#table').val();
                } else {
                    const value = $('#searchResults').val();
                    if (value && value.includes('|')) {
                        const parts = value.split('|');
                        schema = parts[0];
                        table = parts[1];
                    }
                }
                
                if (!schema || !table) {
                    alert('请先选择对象');
                    return;
                }

                $.ajax({
                    url: '/ddl',
                    method: 'GET',
                    data: { 
                        schema: schema, 
                        table: table,
                        type: 'index'
                    },
                    success: function(response) {
                        try {
                            if (!response || typeof response !== 'object') {
                                $('#ddlOutput').val('错误: 无效的响应格式');
                                return;
                            }
                            
                            if (response.status === 'success') {
                                if (response.ddl && typeof response.ddl === 'string') {
                                    // 直接显示原始DDL，避免格式化干扰
                                    $('#ddlOutputCode').text(response.ddl);
                                    // 显示复制按钮
                                    $('#copyBtn').show();
                                    // 移除行号调用
                                    // addLineNumbers();
                                } else {
                                    $('#ddlOutputCode').text('未找到索引DDL语句');
                                    $('#copyBtn').hide();
                                }
                            } else {
                                $('#ddlOutputCode').text('错误: ' + (response.message || '未知错误'));
                                $('#copyBtn').hide();
                            }
                        } catch (e) {
                            console.error("处理索引DDL响应时出错:", e);
                            $('#ddlOutput').val('错误: 处理响应时发生异常');
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error("AJAX错误:", status, error);
                        $('#ddlOutput').val('请求错误: ' + error);
                    }
                });
            });

            $('#getDDLBtn').click(function() {
                let schema, table, objectType, oid;
                
                // 根据当前模式获取schema和table
                if ($('#selectMode').is(':checked')) {
                    schema = $('#schema').val();
                    table = $('#table').val();
                    objectType = $('#objectType').val();
                    // 对于选择模式下的函数和存储过程，获取oid
                    if (objectType === 'function' || objectType === 'procedure') {
                        oid = $('#table option:selected').data('oid');
                        console.log('选择模式下获取的oid:', oid);
                        if (!oid) {
                            // 如果没有获取到oid，尝试从选项文本中解析
                            const optionText = $('#table option:selected').text();
                            console.log('选项文本:', optionText);
                            const match = optionText.match(/\|(\d+)$/);
                            if (match) {
                                oid = match[1];
                                console.log('从文本中解析的oid:', oid);
                            } else {
                                alert('无法获取函数/存储过程的OID，请重新选择对象');
                                return;
                            }
                        }
                    }
                } else {
                    const value = $('#searchResults').val();
                    if (value && value.includes('|')) {
                        const parts = value.split('|');
                        schema = parts[0];
                        table = parts[1];
                        objectType = parts[2] || $('#objectType').val();
                        // 对于函数/存储过程，获取oid
                        if (objectType === 'function' || objectType === 'procedure') {
                            oid = parts.length > 3 ? parts[3] : null;
                            console.log('搜索模式下从value获取的oid:', oid);
                            // 如果没有从parts获取到oid，则从data-oid属性获取
                            if (!oid) {
                                oid = $('#searchResults option:selected').data('oid');
                                console.log('搜索模式下从data-oid获取的oid:', oid);
                            }
                            if (!oid) {
                                alert('无法获取函数/存储过程的OID，请重新选择对象');
                                return;
                            }
                        }
                    }
                }
                
                if (!schema || !table) {
                    alert('请先选择对象');
                    return;
                }

                // 对于函数/存储过程，需要传递oid参数
                const params = {
                    schema: schema,
                    table: table,
                    type: objectType
                };
                
                if (oid) {
                    params.oid = oid;
                }
                
                console.log('发送的请求参数:', params);
                
                $.ajax({
                    url: '/ddl',
                    method: 'GET',
                    data: params,
                    success: function(response) {
                        console.log("DDL响应:", response); // 调试日志
                        try {
                            if (!response || typeof response !== 'object') {
                                $('#ddlOutput').val('错误: 无效的响应格式');
                                return;
                            }
                            
                            if (response.status === 'success') {
                                if (response.ddl && typeof response.ddl === 'string') {
                                    // 直接显示原始DDL，避免格式化干扰
                                    $('#ddlOutputCode').text(response.ddl);
                                    // 显示复制按钮
                                    $('#copyBtn').show();
                                    // 移除行号调用
                                    // addLineNumbers();
                                } else {
                                    $('#ddlOutputCode').text('未找到DDL语句');
                                    $('#copyBtn').hide();
                                }
                            } else {
                                $('#ddlOutputCode').text('错误: ' + (response.message || '未知错误'));
                                $('#copyBtn').hide();
                            }
                        } catch (e) {
                            console.error("处理DDL响应时出错:", e);
                            $('#ddlOutput').val('错误: 处理响应时发生异常');
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error("AJAX错误:", status, error);
                        $('#ddlOutput').val('请求错误: ' + error);
                    }
                });
            });
        });
    </script>
</body>
</html>

